﻿import D3.Matrix;
import D3.ProjectTranceCallBack;
import D3.Vertex;
dynamic class D3.Polygon{
	
	public static var AxesMC:MovieClip;
	public static var AxesLineLenght:Number=50;
	public static var ShowAxes:Boolean;
	
	private var $vertexArray:Array;
	private var $polygonArray:Array;
	private var $centerVertex:D3.Vertex;
	private var $polygonName:String;
	
	private var $axesXVertex:D3.Vertex;
	private var $axesYVertex:D3.Vertex;
	private var $axesZVertex:D3.Vertex;
	
	private var $dorwAxes:Boolean;
	
	private var $axesTranceMatrix:Matrix;
	
	private var $parent:D3.Polygon;
	
	
	private var $mc:MovieClip;
	///
	/**
	 * bingding Polygon with Movieclip 外挂用于创建polygon图形的mc
	 */
	public function get MC():MovieClip{
		return this.$mc;
	}
	/**
	 * bingding Polygon with Movieclip 外挂用于创建polygon图形的mc
	 */
	public function set MC(value:MovieClip){
		this.$mc=value;
	}
	
	//if Draw the Axes
	/**
	 * 是否绘制坐标轴(需要手动清除绘制结果Fun:clearAxes)
	 */
	public function get DrawAxes():Boolean{
		return this.$dorwAxes
	}
	/**
	 * 是否绘制坐标轴(需要手动清除绘制结果Fun:clearAxes)
	 */
	public function set DrawAxes(value:Boolean){
		this.$dorwAxes=value;
	}
	
	//the Trance - Matrix of Axess 
	public function get AxesTranceMatrix():Matrix{
		return this.$axesTranceMatrix;
	}
	public function set AxesTranceMatrix(value:Matrix){
		this.$axesTranceMatrix=value;
	}
	/**
	 * the Center point of Polygon
	 */
	public function get CenterVertex():Vertex{
		return this.$centerVertex;
	}
	/**
	 * 该Polygon的中心点位置
	 */
	public function set CenterVertex(value:Vertex){
		this.$centerVertex=value;
	}
	/**
	 * 该Polygon中所有Polygon列表
	 */
	public function get PolygonArray():Array{
		return this.$polygonArray;
	}
	
	/**
	 * 该Polygon中所有点列表
	 */
	public function get VertexArray():Array{
		return this.$vertexArray;
	}
	/**
	 * 该Polygon的唯一标识名
	 */
	public function get PolygonName():String{
		return this.$polygonName;
	}
	/**
	 * 该Polygon的唯一标识名
	 */
	public function set PolygonName(value:String){
		this.$polygonName=value;
	}
	/**
	 * 该polygon所在的父polygon
	 */
	public function get Parent():Polygon{
		return this.$parent;
	}
	/**
	 * 该polygon所在的父polygon
	 */
	public function set Parent(value:Polygon){
		this.$parent=value;
	}
	
	
	public static var say:Function;
	public function initVers(){
		this.$polygonName="PG";
		this.$centerVertex=new Vertex("PCV",0,0,0);
		this.$axesTranceMatrix=new Matrix();
		this.$axesXVertex=new D3.Vertex("xAxes",AxesLineLenght,0,0);
		this.$axesYVertex=new D3.Vertex("yAxes",0,AxesLineLenght,0);
		this.$axesZVertex=new D3.Vertex("zAxes",0,0,AxesLineLenght);
		this.$dorwAxes=false;
	}
	
	/**
	 * 初始化一个Polygon 按以下几种方式：
	 * Polygon(name)
	 * Polygon(name,v1,v2,v3...)
	 * Polygon(v1,v2,v3...)
	 * Polygon(centerVertex)
	 * Polygon(name,p1,p2,p3...)
	 * Polygon(p1,p2,p3...)
	 */
	public function Polygon(){
		initVers();
		var arg:Array=arguments;
		
		
		if(arg.length==1 && arg[0].VertexName!=undefined){
			//the arguments's type is Vertex
			this.$centerVertex=arg[0];
		}else if(arg.length>1){
			if(typeof(arg[0])=="string"){
				//the first argument's type is string
				this.$polygonName=arg[0];
				arg.shift();
				if(arg[0].VertexName!=undefined){
					for(var i=0;i<arg.length;i++){
						this.AddVertex(arg[i]);
					}
				}else if(arg[0].PolygonName){
					for(var i=0;i<arg.length;i++){
						this.AddPolygon(arg[i]);
					}
				}
			}else if(arg[0].VertexName!=undefined){
				//the first argument's type is't string but Vertex
				for(var i=0;i<arg.length;i++){
					this.AddVertex(arg[i]);
				}
			}else if(arg[0].PolygonName!=undefined){
				//the argument's type is Polygon
				for(var i=0;i<arg.length;i++){
					this.AddPolygon(arg[i]);
				}
			}
		}else if(arg.length==1 && typeof(arg[0])=="string"){
			//polygon name
			this.$polygonName=arg[0];
		}
		else{
			this.wSay("the arguments can't be empty["+arg+"]");
		}
	}
	
	/**
	 * add sub polygons 参数为 polygon
	 */
	public function AddPolygon(){
		var args:Array=arguments;
		if(this.$polygonArray==undefined){
			this.$polygonArray=new Array();
		}
		if(args.length==0){
			wSay("the arguments can't be empty(PG).");
		}
		else if(args[0].PolygonName!=undefined){
			for(var i=0;i<args.length;i++){
				Polygon(args[i]).Parent=this;
				this.$polygonArray.push(args[i]);
			}
		}
	}
	/**
	 * 删除一个子polygon
	 * @param	polygon 子polygon或polygon标识
	 */
	public function DelPolygon(polygon:Object){
		if(typeof(polygon)=="string"){
			for(var i=0;i<this.$polygonArray.length;i++){
				if(this.$polygonName==String(polygon)){
					this.$polygonArray[i].Parent=null;
					var temp=this.$polygonArray[0];
					this.$polygonArray[0]=this.$polygonArray[i];
					this.$polygonArray[i]=temp;
					this.$polygonArray.shift();
				}
			}
		}else if(polygon.PolygonName!=undefined){
			var name:String=Polygon(polygon).PolygonName;
			var cv:Vertex=Polygon(polygon).$centerVertex;
			for(var i=0;i<this.$polygonArray.length;i++){
				if(this.$polygonArray[i].PolygonName==name){
					var tempp:Polygon=Polygon(this.$polygonArray[i]);
					if(tempp.$centerVertex._X==cv._X && tempp.$centerVertex._Y==cv._Y && tempp.$centerVertex._Z==cv._Z){
						this.$polygonArray[i].Parent=null;
						var temp=this.$polygonArray[0];
						this.$polygonArray[0]=this.$polygonArray[i];
						this.$polygonArray[i]=temp;
						this.$polygonArray.shift();
					}
				}
			}
		}else{
			wSay("the polygon's structure not match["+arguments+"]");
		}
	}
	public function removeAllPolygons(){
		var tempp:Array=new Array();
		for(var i=0;i<this.PolygonArray.length;i++){
			tempp.push(this.PolygonArray[i]);
		}
		for(var i=0;i<this.tempp.length;i++){
			this.DelPolygon(this.tempp[i]);
		}
	}
	//add sub Vertexs
	public function AddVertex(){
		var args:Array=arguments;
		if(this.$vertexArray==undefined){
			this.$vertexArray=new Array();
		}
		if(args.length==0){
			wSay("the argument's can't be empty(P).");
		}
		else if(args[0].VertexName!=undefined){
			for(var i=0;i<args.length;i++){
				Vertex(args[i]).Parent=this;
				this.$vertexArray.push(args[i]);
			}
		}
	}
	/**
	 * 清除绘制的坐标
	 */
	public static function clearAxes(){
		if(Polygon.AxesMC!=undefined){
			Polygon.AxesMC.clear();
		}
	}
	/**
	 * 在绑定的movieClip中创建投影
	 * @return
	 */
	public function ProjectAndSetMC():Vertex{
		var lv:Vertex;
		if(this.$mc!=undefined){
			lv=getLocationInParentAxes(this);
			D3.ProjectTranceCallBack.ProjectMcInvoke(this,lv,this.$mc);
		}
		if(this.$vertexArray.length>0){
			for(var i=0;i<this.$vertexArray.length;i++){
				Vertex(this.$vertexArray[i]).ProjectAndSetMC();
			}
		}
		if(this.$polygonArray.length>0){
			for(var i=0;i<this.$polygonArray.length;i++){
				Polygon(this.$polygonArray[i]).ProjectAndSetMC();
			}
		}
		if(this.$dorwAxes || ((Polygon.ShowAxes!=undefined)? Polygon.ShowAxes:false)){
			if(AxesMC!=undefined){
				
				var bl:Number=(ProjectTranceCallBack.DistroyPoint._Z-lv._Z)/ProjectTranceCallBack.DistroyPoint._Z;
				
				AxesMC.lineStyle(0,0xff0000,90);
				AxesMC.moveTo(this.$mc._x,this.$mc._y);
				AxesMC.lineTo(this.$mc._x+this.$axesXVertex._X*bl,this.$mc._y+this.$axesXVertex._Y*bl);
				
				
				AxesMC.lineStyle(0,0x00ff00,90);
				AxesMC.moveTo(this.$mc._x,this.$mc._y);
				AxesMC.lineTo(this.$mc._x+this.$axesYVertex._X*bl,this.$mc._y+this.$axesYVertex._Y*bl);
				
				
				AxesMC.lineStyle(0,0x0000ff,90);
				AxesMC.moveTo(this.$mc._x,this.$mc._y);
				AxesMC.lineTo(this.$mc._x+this.$axesZVertex._X*bl,this.$mc._y+this.$axesZVertex._Y*bl);
				
			}
		}
		return lv;
	}
	private function getLocationInParentAxes(I:Object):Vertex{
		var v:Vertex;
		if(I.PolygonName!=null){
			v=Polygon(I).CenterVertex;
		}else if(I.VertexName!=null){
			v=Vertex(I);
		}else{
			wSay("the arugment's structure not match:"+I);
		}
		if(I.Parent!=undefined){
			var tm:Matrix=getTM(I.Parent);
			var vrs:Vertex=getLocationInParentAxes(I.Parent);
			return v.X(tm).GetMove(vrs._X,vrs._Y,vrs._Z);
		}else{
			return v;
		}
	}
	private function getTM(I:Object):Matrix{
		if(I.AxesTranceMatrix==undefined) {
			wSay("the point(V or P) not in an parent-sreen:"+I);
		}
		if(I.Parent!=undefined){
			return Matrix(I.AxesTranceMatrix).X(getTM(I.Parent));
		}else{
			return Matrix(I.AxesTranceMatrix);
		}
	}
	public function axesXRotation2(p:Number){
		var tm:D3.Matrix=Matrix.getXRotation(p);
		this.$axesXVertex=this.$axesXVertex.X(tm);
		this.$axesYVertex=this.$axesYVertex.X(tm);
		this.$axesZVertex=this.$axesZVertex.X(tm);
		this.$axesTranceMatrix=this.$axesTranceMatrix.X(tm);
	}
	public function axesYRotation2(p:Number){
		var tm:D3.Matrix=Matrix.getYRotation(p);
		this.$axesXVertex=this.$axesXVertex.X(tm);
		this.$axesYVertex=this.$axesYVertex.X(tm);
		this.$axesZVertex=this.$axesZVertex.X(tm);
		this.$axesTranceMatrix=this.$axesTranceMatrix.X(tm);
	}
	public function axesZRotation2(p:Number){
		var tm:D3.Matrix=Matrix.getZRotation(p);
		this.$axesYVertex=this.$axesYVertex.X(tm);
		this.$axesXVertex=this.$axesXVertex.X(tm);
		this.$axesZVertex=this.$axesZVertex.X(tm);
		this.$axesTranceMatrix=this.$axesTranceMatrix.X(tm);
	}
	//Polygon rotate on self X-Axes 
	public function axesXRotation(p:Number){
		var tm:D3.Matrix=Matrix.getFreeAxisRotation(this.$axesXVertex._X,this.$axesXVertex._Y,this.$axesXVertex._Z,p);
		this.$axesYVertex=this.$axesYVertex.X(tm);
		this.$axesZVertex=this.$axesZVertex.X(tm);
		this.$axesTranceMatrix=this.$axesTranceMatrix.X(tm);
		
	}
	//Polygon rotate on self Y-Axes 
	public function axesYRotation(p:Number){
		
		var tm:D3.Matrix=Matrix.getFreeAxisRotation(this.$axesYVertex._X,this.$axesYVertex._Y,this.$axesYVertex._Z,p);
		this.$axesXVertex=this.$axesXVertex.X(tm);
		this.$axesZVertex=this.$axesZVertex.X(tm);
		this.$axesTranceMatrix=this.$axesTranceMatrix.X(tm);
		
		
	}
	//Polygon rotate on self Z-Axes 
	public function axesZRotation(p:Number){
		var tm:D3.Matrix=Matrix.getFreeAxisRotation(this.$axesZVertex._X,this.$axesZVertex._Y,this.$axesZVertex._Z,p);
		this.$axesXVertex=this.$axesXVertex.X(tm);
		this.$axesYVertex=this.$axesYVertex.X(tm);
		this.$axesTranceMatrix=this.$axesTranceMatrix.X(tm);
	}
	
	//Polygon rotate in parent-screen on parent X-Axes
	/**
	 * 延X轴旋转一定弧度
	 * @param	O 弧度
	 */
	public function XRotation(O:Number){
		if(this.$parent!=undefined){
			this.$centerVertex.XRotation(O);
		}else{
			wSay("this polgon not's in an screen");
		}
	}
	
	//Polygon rotate in parent-screen on parent Y-Axes
	/**
	 * 延Y轴旋转一定弧度
	 * @param	O 弧度
	 */
	public function YRotation(O:Number){
		if(this.$parent!=undefined){
			this.$centerVertex.YRotation(O);
		}else{
			wSay("this polgon not's in an screen");
		}
	}
	
	//Polygon rotate in parent-screen on parent Z-Axes
	/**
	 * 延Z轴旋转一定弧度
	 * @param	O 弧度
	 */
	public function ZRotation(O:Number){
		if(this.$parent!=undefined){
			this.$centerVertex.ZRotation(O);
		}else{
			wSay("this polgon not's in an screen");
		}
	}
	
	//
	/**
	 * Polygon rotate in parent-screen on parent free-Axes
	 * @param	x Vertex 或是x值
	 * @param	y y值
	 * @param	z z值
	 * @param	O 转动弧度
	 */
	public function FreeRotation(x:Object,y:Number,z:Number,O:Number){
		if(this.$parent!=undefined){
			this.$centerVertex.FreeRotation(x,y,z,O);
		}else{
			wSay("this polgon not's in an screen");
		}
	}
	
	/**
	 * Polygon move to the point that in parent-screen
	 * @param	x x值
	 * @param	y y值
	 * @param	z z值
	 */
	public function MoveTo(x:Number,y:Number,z:Number){
		if(this.$parent!=undefined){
			this.$centerVertex.MoveTo(x,y,z);
		}else{
			wSay("this polgon not's in an screen");
		}
	}
	//
	/**
	 * Polygon move an offset value in parent-screen
	 * @param	x x移动量
	 * @param	y y移动量
	 * @param	z z移动量
	 */
	public function Move(x:Number,y:Number,z:Number){
		if(this.$parent!=undefined){
			this.$centerVertex.Move(x,y,z);
		}else{
			wSay("this polgon not's in an screen");
		}
	}
	
	//rotation sub polgons and vertens in this screen on this X-Axes
	public function subXRotation(O:Number){
		for(var i=0;i<this.$vertexArray.length;i++){
			Vertex(this.$vertexArray[i]).XRotation(O);
		}
		for(var i=0;i<this.$polygonArray.length;i++){
			Polygon(this.$polygonArray[i]).XRotation(O);
		}
	}
	
	//rotation sub polgons and vertens in this screen on this Y-Axes
	public function subYRotation(O:Number){
		for(var i=0;i<this.$vertexArray.length;i++){
			Vertex(this.$vertexArray[i]).YRotation(O);
		}
		for(var i=0;i<this.$polygonArray.length;i++){
			Polygon(this.$polygonArray[i]).YRotation(O);
		}
	}
	
	//rotation sub polgons and vertens in this screen on this Z-Axes
	public function subZRotation(O:Number){
		for(var i=0;i<this.$vertexArray.length;i++){
			Vertex(this.$vertexArray[i]).ZRotation(O);
		}
		for(var i=0;i<this.$polygonArray.length;i++){
			Polygon(this.$polygonArray[i]).ZRotation(O);
		}
	}
	
	//move sub polygon or vertexs to the point in this screen
	public function subMove(x:Number,y:Number,z:Number){
		for(var i=0;i<this.$vertexArray.length;i++){
			Vertex(this.$vertexArray[i]).Move(x,y,z);
		}
		for(var i=0;i<this.$polygonArray.length;i++){
			Polygon(this.$polygonArray[i]).Move(x,y,z);
		}
	}
	//
	/**
	 * rotation sub polgons and vertens in this screen on this Free-Axes
	 * @param	x 
	 * @param	y
	 * @param	z
	 * @param	O
	 */
	public function subFreeRotation(x:Object,y:Number,z:Number,O:Number){
		for(var i=0;i<this.$vertexArray.length;i++){
			Vertex(this.$vertexArray[i]).FreeRotation(x,y,z,O);
		}
		for(var i=0;i<this.$polygonArray.length;i++){
			Polygon(this.$polygonArray[i]).FreeRotation(x,y,z,O);
		}
	}
	
	
	
	public function Say(o:Object){
		if(Polygon.say!=undefined){
			Polygon.say(this.$polygonName+": "+o.toString());
		}
	}
	public function wSay(o:Object){
		var s:String="**WARN** "+this.$polygonName+": "+o.toString()
		if(Polygon.say!=undefined){
			Polygon.say(s);
		}else{
			trace(s);
		}
	}
	
	
	public function toString(all:Boolean, args:Boolean)
	{
		if (args == undefined) {
			args = false;
		}
		var str:String="-------["+this.$polygonName+" "+this.$centerVertex.toString()+"]-------\n";
		if(all==true){
			for (var i = 0; i < this.$vertexArray.length; i++) {
				if(!args){
					str += this.$vertexArray[i].toString() + "\n";
				}else {
					str += this.$vertexArray[i].toString("point") + "\n";
				}
			}
			str+="------------------"
		}
		return str;
	}
}